package im.actor.runtime.js.webrtc;
import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.core.client.JavaScriptObject;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import im.actor.runtime.function.CountedReference;
import im.actor.runtime.js.entity.JsClosure;
import im.actor.runtime.js.entity.JsClosureError;
import im.actor.runtime.js.webrtc.js.JsMediaStream;
import im.actor.runtime.js.webrtc.js.JsPeerConnection;
import im.actor.runtime.js.webrtc.js.JsPeerConnectionListener;
import im.actor.runtime.js.webrtc.js.JsRTCIceCandidate;
import im.actor.runtime.js.webrtc.js.JsSessionDescription;
import im.actor.runtime.js.webrtc.js.JsSessionDescriptionCallback;
import im.actor.runtime.promise.Promise;
import im.actor.runtime.promise.PromiseFunc;
import im.actor.runtime.promise.PromiseResolver;
import im.actor.runtime.webrtc.WebRTCMediaStream;
import im.actor.runtime.webrtc.WebRTCPeerConnection;
import im.actor.runtime.webrtc.WebRTCPeerConnectionCallback;
import im.actor.runtime.webrtc.WebRTCSessionDescription;
public class PeerConnection implements WebRTCPeerConnection {
private JsPeerConnection peerConnection;
private ArrayList<WebRTCPeerConnectionCallback> callbacks = new ArrayList<>();
private HashMap<JsMediaStream, MediaStream> streams = new HashMap<>();
public PeerConnection(JsPeerConnection peerConnection) {
this.peerConnection = peerConnection;
this.peerConnection.setListener(new JsPeerConnectionListener() {
@Override
public void onIceCandidate(JsRTCIceCandidate candidate) {
for (WebRTCPeerConnectionCallback c : callbacks) {
c.onCandidate(candidate.getLabel(), candidate.getId(), candidate.getSDP());
}
}
@Override
public void onStreamAdded(JsMediaStream stream) {
MediaStream stream1 = new MediaStream(stream);
streams.put(stream, stream1);
for (WebRTCPeerConnectionCallback c : callbacks) {
c.onStreamAdded(stream1);
}
}
@Override
public void onStreamRemoved(JsMediaStream stream) {
MediaStream stream1 = streams.get(stream);
if (stream1 != null) {
for (WebRTCPeerConnectionCallback c : callbacks) {
c.onStreamRemoved(stream1);
}
}
}
@Override
public void onRenegotiationNeeded() {
for (WebRTCPeerConnectionCallback c : callbacks) {
c.onRenegotiationNeeded();
}
}
});
}
@Override
public void addCallback(@NotNull WebRTCPeerConnectionCallback callback) {
if (!callbacks.contains(callback)) {
callbacks.add(callback);
}
}
@Override
public void removeCallback(@NotNull WebRTCPeerConnectionCallback callback) {
callbacks.remove(callback);
}
@Override
public void addCandidate(int label, @NotNull String id, @NotNull String candidate) {
peerConnection.addIceCandidate(label, candidate);
}
@Override
public void addOwnStream(@NotNull CountedReference<WebRTCMediaStream> stream) {
peerConnection.addStream(((MediaStream) stream.get()).getStream());
}
@Override
public void removeOwnStream(@NotNull CountedReference<WebRTCMediaStream> stream) {
peerConnection.removeStream(((MediaStream) stream.get()).getStream());
}
@NotNull
@Override
public Promise<WebRTCSessionDescription> setLocalDescription(@NotNull final WebRTCSessionDescription description) {
return new Promise<>(new PromiseFunc<WebRTCSessionDescription>() {
@Override
public void exec(@NotNull final PromiseResolver<WebRTCSessionDescription> resolver) {
peerConnection.setLocalDescription(JsSessionDescription.create(description.getType(), description.getSdp()), () -> {
resolver.result(description);
}, error -> resolver.error(new JavaScriptException(error)));
}
}
);
}
@NotNull
@Override
public Promise<WebRTCSessionDescription> setRemoteDescription(@NotNull final WebRTCSessionDescription description) {
return new Promise<>(new PromiseFunc<WebRTCSessionDescription>() {
@Override
public void exec(@NotNull final PromiseResolver<WebRTCSessionDescription> resolver) {
peerConnection.setRemoteDescription(JsSessionDescription.create(description.getType(),
description.getSdp()), new JsClosure() {
@Override
public void callback() {
resolver.result(description);
}
}, new JsClosureError() {
@Override
public void onError(JavaScriptObject error) {
resolver.error(new JavaScriptException(error));
}
});
}
});
}
@NotNull
@Override
public Promise<WebRTCSessionDescription> createOffer() {
return new Promise<>(new PromiseFunc<WebRTCSessionDescription>() {
@Override
public void exec(@NotNull final PromiseResolver<WebRTCSessionDescription> resolver) {
peerConnection.createOffer(new JsSessionDescriptionCallback() {
@Override
public void onOfferCreated(JsSessionDescription offer) {
resolver.result(new WebRTCSessionDescription(offer.getType(), offer.getSDP()));
}
@Override
public void onOfferFailure() {
resolver.error(new RuntimeException());
}
});
}
});
}
@NotNull
@Override
public Promise<WebRTCSessionDescription> createAnswer() {
return new Promise<>(new PromiseFunc<WebRTCSessionDescription>() {
@Override
public void exec(@NotNull final PromiseResolver<WebRTCSessionDescription> resolver) {
peerConnection.createAnswer(new JsSessionDescriptionCallback() {
@Override
public void onOfferCreated(JsSessionDescription offer) {
resolver.result(new WebRTCSessionDescription(offer.getType(), offer.getSDP()));
}
@Override
public void onOfferFailure() {
resolver.error(new RuntimeException());
}
});
}
});
}
@Override
public void close() {
if (peerConnection != null) {
peerConnection.close();
peerConnection = null;
}
for (MediaStream s : streams.values()) {
s.close();
}
streams.clear();
}
}